package com.ynet.middleground.riskmanage.model;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Throwables;
import com.ynet.core.common.BaseReqObj;
import com.ynet.core.common.PagerInfo;
import com.ynet.core.exception.BusinessException;
import com.ynet.core.log.IfpLogger;
import com.ynet.middleground.riskmanage.bean.*;
import com.ynet.middleground.riskmanage.common.SystemConstant;
import com.ynet.middleground.riskmanage.dao.*;
import com.ynet.middleground.riskmanage.dto.*;
import com.ynet.middleground.riskmanage.entity.*;
import com.ynet.middleground.riskmanage.external.MainBusinessConfig;
import com.ynet.middleground.riskmanage.external.codechain.ColdChainApiHelper;
import com.ynet.middleground.riskmanage.external.codechain.ColdChainUriEnum;
import com.ynet.middleground.riskmanage.model.coldchain.ColdchainDynamicPledgeHistoryModel;
import com.ynet.middleground.riskmanage.model.coldchain.ColdchainDynamicPledgeModel;
import com.ynet.middleground.riskmanage.mq.producer.ColdChainProducer;
import com.ynet.middleground.riskmanage.mq.producer.ZtProducer;
import com.ynet.middleground.riskmanage.utils.BeanUtil;

/**
 * @ClassName ColdChainModel
 * @Description 冷链服务处理逻辑
 * @Author zhangyongbin
 * @Date 2020/8/14 16:32
 * @Version 1.0
 */
@Component
public class ColdChainModel {

    // /**
    // * 冷链分配给中台的账户号，每次请求接口时添加上该参数，用于冷链的权限管理
    // */
    // private static final String REQ_ACCOUNT_ID = "111";

    @Autowired
    ColdChainApiHelper apiHelper;

    @Autowired
    private Mapper mapper;

    @Autowired
    ColdChainGoodsTypeModel ColdChainGoodsTypeModel;

    @Autowired
    private ColdchainGoodsTypeMapper coldchainGoodsTypeMapper;

    @Autowired
    ColdChainStockInfoModel coldChainStockInfoModel;

    @Autowired
    ColdChainStockHistoryInfoModel coldChainStockHistoryInfoModel;

    @Autowired
    ColdChainStaticPledgeMapper coldChainStaticPledgeMapper;

    @Autowired
    ColdChainDynamicPledgeMapper coldChainDynamicPledgeMapper;

    @Autowired
    ColdchainDynamicPledgeModel dynamicPledgeModel;

    @Autowired
    ColdchainDynamicPledgeHistoryModel dynamicPledgeHistoryModel;

    @Autowired
    ColdchainHistoryRespMapper coldchainHistoryRespMapper;

    @Autowired
    ColdChainStockInfoHistoryMapper coldChainStockHistoryInfoMapper;

    @Autowired
    ColdChainStockInfoMapper coldChainStockInfoMapper;

    @Autowired
    ZtProducer ztProducer;

    @Autowired
    MainBusinessConfig mainBusinessConfig;

    @Autowired
    ColdchainCustomerApplyMapper coldchainCustomerApplyMapper;

    @Autowired
    ColdChainProducer coldChainProducer;

    @Autowired
    MainBusinessConfig config;

    /**
     * @return java.util.List<com.ynet.middleground.riskmanage.dto.ColdChainHistoryBusinessVolumeDTO>
     * @Description 历史业务量查询处理
     * @Date 16:39 2020/8/14
     * @Param [req]请求信息
     **/
    @Transactional(rollbackFor = Exception.class)
    public List<ColdChainHistoryBusinessVolumeDTO> getHistoryBusinessVolume(ColdChainHistoryBusinessVolumeReq req) {

        if (org.apache.commons.lang3.StringUtils.isBlank(req.getUserNo())
            && org.apache.commons.lang3.StringUtils.isBlank(req.getUserName())) {
            throw new BusinessException("货主账号和货主名称不能同时为空", "ECRM0001");
        }

        Map<String, Object> params = new HashMap<>(5);
        // params.put("accountId", REQ_ACCOUNT_ID);
        params.put("accountId", mainBusinessConfig.getColdchainAccount());
        params.put("custName", req.getUserName());
        params.put("customerNumber", req.getUserNo());
        params.put("itemClass", req.getTypes());
        // 查询类型
        params.put("seachtype", "历史业务量");
        params.put("instorageDate", req.getStarorendDate());
        JSONObject apiResult = apiHelper.sendApi(ColdChainUriEnum.GET_HISTORY_BUSINESS_VOLUME, params, req);

        // JSONObject apiResult = JSONObject.parseObject(
        // "{\"result\":[{\"customerNumber\":\"123\",\"customerName\":\"123\",\"itemClass\":\"123\",\"itemClassName\":\"123\",\"historyAmount\":\"123\",\"historyWeight\":\"123\",\"instorageDate\":\"123\"},{\"customerNumber\":\"123\",\"customerName\":\"123\",\"itemClass\":\"1231\",\"itemClassName\":\"123\",\"historyAmount\":\"123\",\"historyWeight\":\"123\",\"instorageDate\":\"123\"}],\"success\":true,\"errorMsg\":\"\",\"errorCode\":\"0\"}");
        Integer code = apiResult.getInteger("errorCode");
        String message = apiResult.getString("errorMsg");
        if (!code.equals(ColdChainApiHelper.STATUS_SUCCESS)) {
            throw new BusinessException(message, String.valueOf(code));
        }

        JSONArray result = apiResult.getJSONArray("result");
        List<ColdchainHistoryResp> coldchainHistoryRespList = null;

        List<ColdChainHistoryBusinessVolumeDTO> dtoList = new ArrayList<>();

        if (result != null && result.size() > 0) {
            Map<String, String> change = new HashMap<>();
            change.put("instorageDate", "enterStockTime");
            result = BeanUtil.changeJsonArr(result, change);
            coldchainHistoryRespList = result.toJavaList(ColdchainHistoryResp.class);
            for (ColdchainHistoryResp volume : coldchainHistoryRespList) {
                BeanUtil.setGenericInfo(volume, req);
                dtoList.add(historyDataConvert(volume));
            }

            coldchainHistoryRespMapper.insertBatchHistory(coldchainHistoryRespList);
        }

        return dtoList;

    }

    /**
     * @return com.ynet.middleground.riskmanage.dto.ColdChainHistoryBusinessVolumeDTO
     * @Description 历史业务量信息实体类转DTO
     * @Author zhangyongbin
     * @Date 2020/8/16 15:04
     * @Param [coldChainBusinessVolume]
     **/
    private ColdChainHistoryBusinessVolumeDTO historyDataConvert(ColdchainHistoryResp entity) {

        ColdChainHistoryBusinessVolumeDTO dto = new ColdChainHistoryBusinessVolumeDTO();
        dto.setUserNo(entity.getCustomerNumber()).setUserName(entity.getCustomerName())
            .setTypeCode(entity.getItemClass()).setTypeName(entity.getItemClassName())
            .setHisAmount(entity.getHistoryAmount()).setHisHeight(entity.getHistoryWeight())
            .setDatetimes(entity.getEnterStockTime());
        return dto;
    }

    /**
     * @return java.util.List<com.ynet.middleground.riskmanage.dto.ColdChainStockInfoDTO>
     * @Description 在库信息查询
     * @Author zhangyongbin
     * @Date 2020/8/18 11:10
     * @Param [req]在库信息查询请求信息
     **/
    public List<ColdChainStockInfoDTO> getStockInfo(ColdChainStockInfoReq req) {
        // Add By liwq On 2021-01-27 Start
        // 增加排序功能&指定字段排序功能
        if (!StringUtils.isEmpty(req.getSortField()) && StringUtils.isEmpty(req.getSortOrder())) {
            throw new BusinessException("请上送排序方式", "DAGM0001");
        }
        if (StringUtils.isEmpty(req.getSortField())
            && !org.apache.commons.lang3.StringUtils.isEmpty(req.getSortOrder())) {
            throw new BusinessException("请上送排序字段", "DAGM0002");
        }
        if (!StringUtils.isEmpty(req.getSortField())) {
            List<String> dagangSortField = mainBusinessConfig.getColdchainSortField();
            if (dagangSortField.size() == 0) {
                throw new BusinessException("请联系管理员维护冷链有效排序字段", "DAGM0004");
            }
            if (dagangSortField.size() > 0) {
                if (!dagangSortField.contains(req.getSortField())) {
                    throw new BusinessException("请上送有效排序字段", "DAGM0003");
                }
            }
        }
        // Add By liwq On 2021-01-27 End

        if (org.apache.commons.lang3.StringUtils.isBlank(req.getUserNo())
            && org.apache.commons.lang3.StringUtils.isBlank(req.getUserName())) {
            throw new BusinessException("货主账号和货主名称不能同时为空", "ECRM0001");
        }

        Map<String, Object> params = new HashMap<>(5);
        // params.put("accountId", REQ_ACCOUNT_ID);
        params.put("accountId", mainBusinessConfig.getColdchainAccount());
        params.put("customerNumber", req.getUserNo());
        params.put("custName", req.getUserName());
        params.put("itemClass", req.getTypes());
        params.put("seachtype", "在库信息");
        params.put("id", req.getId());

        // Add By Liwq On 2021-01-27 Start
        // 增加排序功能&指定字段排序功能
        if (!StringUtils.isEmpty(req.getSortField()) && !StringUtils.isEmpty(req.getSortOrder())) {
            params.put("sortField", req.getSortField());
            params.put("sortOrder", req.getSortOrder());
        }
        if (!StringUtils.isEmpty(String.valueOf(req.getPagerInfo().getPageNum()))) {
            params.put("pageNum", req.getPagerInfo().getPageNum());
        }
        if (!StringUtils.isEmpty(String.valueOf(req.getPagerInfo().getPageSize()))) {
            params.put("pageSize", req.getPagerInfo().getPageSize());
        }
        if (!StringUtils.isEmpty(String.valueOf(req.getPagerInfo().getTotal()))) {
            params.put("total", req.getPagerInfo().getPageSize());
        }
        // Add By Liwq On 2021-01-27 End

        JSONObject apiResult = apiHelper.sendApi(ColdChainUriEnum.GET_STOCK_INFO, params, req);

        // JSONObject apiResult = JSONObject.parseObject(
        // "{\"result\":[{\"id\":\"231\",\"tdh\":\"666\",\"xh\":\"666\",\"item\":\"123\",\"itemname\":\"123\",\"location\":\"123\",\"itemStatus\":\"123\",\"instorageDate\":\"2020-08-18\",\"qty\":\"1423\",\"netWeight\":\"3453\",\"grossWeight\":\"345\",\"totalNetweight\":\"345\",\"totalGrossweight\":\"345\",\"pledge\":\"2314\",\"pledheWeight\":\"2134\"},{\"id\":\"3453456\",\"tdh\":\"123\",\"xh\":\"123\",\"item\":\"123\",\"itemname\":\"123\",\"location\":\"123\",\"itemStatus\":\"123\",\"instorageDate\":\"2020-08-18\",\"qty\":\"1423\",\"netWeight\":\"3453\",\"grossWeight\":\"345\",\"totalNetweight\":\"345\",\"totalGrossweight\":\"345\",\"pledge\":\"2314\",\"pledheWeight\":\"2134\"}],\"success\":true,\"errorMsg\":\"\",\"errorCode\":\"0\"}");
        Integer code = apiResult.getInteger("errorCode");
        String message = apiResult.getString("errorMsg");
        if (!code.equals(ColdChainApiHelper.STATUS_SUCCESS)) {
            throw new BusinessException(message, String.valueOf(code));
        }

        JSONArray result = apiResult.getJSONArray("result");

        // Add By Liwq On 2021-01-27 Start
        // 总条数
        Integer total = apiResult.getInteger("total");
        req.getPagerInfo().setTotal(total);
        // Add By Liwq On 2021-01-27 End

        List<ColdChainStockInfo> coldChainStockInfoList = null;

        /**
         * 返回结果
         */
        List<ColdChainStockInfoDTO> dtoList = null;

        if (result != null) {
            Map<String, String> map = new HashMap(1);
            // 进行key值转换
            map.put("id", "detailId");
            result = BeanUtil.changeJsonArr(result, map);
            coldChainStockInfoList = result.toJavaList(ColdChainStockInfo.class);
            dtoList = new ArrayList<>(coldChainStockInfoList.size());
            /**
             * 获取业务主键ID
             */
            List<String> bidList = new ArrayList<>();
            /**
             * 历史库存数据信息
             */
            List<ColdChainStockHistoryInfo> historyList = new ArrayList<>(coldChainStockInfoList.size());

            for (ColdChainStockInfo stockInfo : coldChainStockInfoList) {
                BeanUtil.setGenericInfo(stockInfo, req);
                /**
                 * 实时数据转换为历史数据
                 */
                ColdChainStockHistoryInfo historyInfo = mapper.map(stockInfo, ColdChainStockHistoryInfo.class);
                historyList.add(historyInfo);

                bidList.add(stockInfo.getDetailId());
                /**
                 * 实体类转换DTO
                 */
                dtoList.add(convertStockData(stockInfo));
            }
            if (historyList.size() > 0) {
                coldChainStockHistoryInfoMapper.insertBatchHistory(historyList);
            }
            LambdaQueryWrapper<ColdChainStockInfo> queryWrapper = new LambdaQueryWrapper<>();
            /**
             * 根据业务ID查询已存在于数据库里的库存数据
             */
            // if (bidList.size() > 0) {
            // queryWrapper.in(ColdChainStockInfo::getDetailId, bidList);
            // }
            // List<ColdChainStockInfo> existList = coldChainStockInfoModel.list(queryWrapper);

            /**
             * 循环判断哪些数据需要更新，哪些是新增
             */
            // for (ColdChainStockInfo stockInfo : coldChainStockInfoList) {
            // for (ColdChainStockInfo extisStockInfo : existList) {
            // if ((stockInfo.getDetailId()).equals(extisStockInfo.getDetailId())) {
            // /**
            // * 根据业务ID判断数据已经存在，进行更改
            // */
            // stockInfo.setId(extisStockInfo.getId());
            // break;
            // }
            // }
            // }
            // 保存或更新数据
            if (coldChainStockInfoList.size() > 0) {
                coldChainStockInfoMapper.insertOrUpdateBatch(coldChainStockInfoList);
            }
        }
        return dtoList;
    }

    /**
     * 在库信息实体类转DTO
     *
     * @param entity
     * @return
     */
    private ColdChainStockInfoDTO convertStockData(ColdChainStockInfo entity) {
        ColdChainStockInfoDTO dto = new ColdChainStockInfoDTO();

        dto.setId(entity.getDetailId()).setBillNo(entity.getTdh()).setContainerNo(entity.getXh())
            .setTypeCode(entity.getItem()).setTypeName(entity.getItemname()).setLocation(entity.getLocation())
            .setSellState(entity.getItemStatus()).setStoreDate(stringToDate(entity.getInstorageDate()))
            .setNumber(entity.getQty()).setNetWeitght(entity.getNetWeight()).setRoughWeight(entity.getGrossWeight())
            .setSumNetWeigth(entity.getTotalNetweight()).setSumRoughWeight(entity.getTotalGrossweight())
            .setPledgeState(entity.getPledge()).setPledgeWeight(entity.getPledgeWeight())
            .setPledgeAmount(entity.getPledgeAmount());

        return dto;
    }

    /**
     * 字符串转Date
     *
     * @throws ParseException
     */
    public Date stringToDate(String str) {
        if (StringUtils.isEmpty(str)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return sdf.parse(str);
        } catch (ParseException e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "数据类型转换异常, case: {}",
                Throwables.getStackTraceAsString(e));
        }
        return new Date();
    }

    /**
     * @return ColdchainGoodsTypeDTO
     * @author songyf
     * @Description 货种小类信息查询
     * @Date 2020-08-17 14:36
     * @Param ColdchainGoodsTypeQueryReqPager
     **/
    public List<ColdchainGoodsTypeDTO> getColdchainGoodsType(ColdchainGoodsTypeQueryReqPager req) {
        LambdaQueryWrapper<ColdchainGoodsType> queryWrapper = new LambdaQueryWrapper<ColdchainGoodsType>();
        if (!StringUtils.isEmpty(req.getTypeCode())) {
            queryWrapper.eq(ColdchainGoodsType::getType, req.getTypeCode());
        }
        PagerInfo pagerInfo = req.getPagerInfo();
        Page<ColdchainGoodsType> coldchainGoodsTypePage = new Page<>(pagerInfo.getPageNum(), pagerInfo.getPageSize());
        IPage<ColdchainGoodsType> page = coldchainGoodsTypeMapper.selectPage(coldchainGoodsTypePage, queryWrapper);
        List<ColdchainGoodsType> list = page.getRecords();
        List<ColdchainGoodsTypeDTO> coldchainGoodsTypeDTOList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            ColdchainGoodsTypeDTO coldchainGoodsTypeDTO = new ColdchainGoodsTypeDTO();
            coldchainGoodsTypeDTO.setTypeCode(list.get(i).getType());
            coldchainGoodsTypeDTO.setTypeName(list.get(i).getName());
            coldchainGoodsTypeDTOList.add(coldchainGoodsTypeDTO);
        }
        pagerInfo.setTotal(page.getTotal());
        return coldchainGoodsTypeDTOList;
    }

    /**
     * @param requestObject
     * @return
     * @author songyf
     * @Description 货种小类信息同步
     * @Date 2020-08-17 16:36
     */
    @Transactional(rollbackFor = Exception.class)
    public String coldchainGoodsTypeSyn(ColdchainGoodsTypeReq requestObject) {
        List<ColdchainGoodsType> list = new ArrayList<>();
        List<ColdchainGoodsType> updateList = new ArrayList<>();
        List<ColdchainGoodsTypeInformation> coldchainGoodsTypeInformations = requestObject.getColdchainGoodsType();
        List<String> typeList = new ArrayList<String>();
        for (int a = 0; a < coldchainGoodsTypeInformations.size(); a++) {
            typeList.add(coldchainGoodsTypeInformations.get(a).getTypeCode());
        }
        LambdaQueryWrapper<ColdchainGoodsType> QueryWrapperCGT = new LambdaQueryWrapper<ColdchainGoodsType>();
        QueryWrapperCGT.in(ColdchainGoodsType::getType, typeList);
        List<ColdchainGoodsType> coldchainGoodsTypes = coldchainGoodsTypeMapper.selectList(QueryWrapperCGT);
        for (int i = 0; i < coldchainGoodsTypeInformations.size(); i++) {
            ColdchainGoodsType coldchainGoodsType = new ColdchainGoodsType();
            ColdchainGoodsTypeInformation coldchainGoodsTypeReq = coldchainGoodsTypeInformations.get(i);
            coldchainGoodsType.setType(coldchainGoodsTypeReq.getTypeCode());
            coldchainGoodsType.setName(coldchainGoodsTypeReq.getTypeName());
            coldchainGoodsType.setCreateBy(requestObject.getOperationUserId());
            coldchainGoodsType.setGmtCreate(LocalDateTime.now());
            coldchainGoodsType.setGmtModified(LocalDateTime.now());
            coldchainGoodsType.setModifiedBy(requestObject.getOperationUserId());
            list.add(coldchainGoodsType);
        }
        for (int b = 0; b < list.size(); b++) {
            ColdchainGoodsType coldchainGoodsType = list.get(b);
            for (int j = 0; j < coldchainGoodsTypes.size(); j++) {
                ColdchainGoodsType coldchainGoodsTypeUpdate = coldchainGoodsTypes.get(j);
                if (coldchainGoodsType.getType().equals(coldchainGoodsTypeUpdate.getType())) {
                    list.get(b).setId(coldchainGoodsTypeUpdate.getId());
                    break;
                }
            }
        }
        // LambdaQueryWrapper<ColdchainGoodsType> deleteColdchainGoodsType = new
        // LambdaQueryWrapper<ColdchainGoodsType>();
        // deleteColdchainGoodsType.like(ColdchainGoodsType::getId, "");
        // ColdChainGoodsTypeModel.remove(deleteColdchainGoodsType);
        ColdChainGoodsTypeModel.saveOrUpdateBatch(list);
        List<Map<String, String>> mapList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            Map<String, String> map = new HashMap<>();
            map.put("id", list.get(i).getType());
            map.put("name", list.get(i).getName());
            mapList.add(map);
        }
        JSONArray data = JSONArray.parseArray(JSON.toJSONString(mapList));
        ztProducer.sendMessagesColdGoodsTypeIn(requestObject, data);
        String returnsResult = SystemConstant.SYSTEM_SUCCESS;
        return returnsResult;
    }

    /**
     * TODO: 测试专用 测试查询动态质押数据，模拟返回数据
     *
     * @return 模拟动态质押数据
     * @author liulx
     * @date 2020-08-18 15:51:20
     */
    public JSONObject testDynamicPledgeData() {
        String testData =
            "{\"result\":[{\"id\":1,\"customerNumber\":\"11222S\",\"item\":\"001\",\"itemName\":\"黄花鱼\",\"lessWeight\":22522,\"lessAmount\":22522,\"pledge\":\"张丹\"},{\"id\":2,\"customerNumber\":\"11222S\",\"item\":\"002\",\"itemName\":\"牛肉\",\"lessWeight\":22522,\"lessAmount\":22522,\"pledge\":\"张丹\"}],\"pagerInfo\":{\"pageNum\":1,\"pageSize\":10,\"total\":2},\"success\":true,\"errorMsg\":\"\",\"errorCode\":\"0\"}";
        return JSONObject.parseObject(testData);
    }

    /**
     * 查询冷链系统中现已动态质押的数据
     *
     * @param req 查询冷链动态质押数据请求信息
     * @return 动态质押数据集合
     * @author liulx
     */
    public List<ColdchainDynamicPledgeDTO> listDynamicPledge(ColdchainDynamicPledgeQueryReq req) {
        Map<String, Object> params = new HashMap<>(4);
        // params.put("accountId", REQ_ACCOUNT_ID);
        params.put("accountId", mainBusinessConfig.getColdchainAccount());
        params.put("customerNumber", req.getUserNo());
        // TODO: 此处 searchtype 的含义为：动态质押数据，具体的值待冷链提供
        params.put("seachtype", "动态质押数据");
        params.put("itemClass", req.getTypes());

        JSONObject apiResult = apiHelper.sendApi(ColdChainUriEnum.DYNAMIC_PLEDGE, params, req);
        // JSONObject apiResult = testDynamicPledgeData();
        Integer code = apiResult.getInteger("errorCode");
        String message = apiResult.getString("errorMsg");
        if (code == null || code != 0) {
            throw new BusinessException(message, message);
        }
        JSONArray objects = apiResult.getJSONArray("result");
        if (objects == null || objects.size() == 0) {
            return Collections.emptyList();
        }
        List<ColdchainDynamicPledgeResp> list = new ArrayList<>(objects.size());
        for (int i = 0; i < objects.size(); i++) {
            JSONObject object = objects.getJSONObject(i);
            ColdchainDynamicPledgeResp resp = object.toJavaObject(ColdchainDynamicPledgeResp.class);
            // 调整字段，实际上返回的 id 并非中台数据库中的 id，应该是 detail_id
            resp.setId(null);
            resp.setDetailId(object.getString("id"));
            list.add(resp);
        }
        return processRespListData(list, req);
    }

    /**
     * <pre>
     *      处理接口最新返回的数据，并将数据插入历史表中。
     *      针对最新数据处理方式：根据数据中每个业务 id 号，判断是否已经存在于数据库中
     *      如果已存在数据库，则将数据库中的数据更新为最新的数据;
     *      若不存在数据库中，则新增
     * </pre>
     *
     * <note> 当前查询的动态质押数据业务主键使用「detail_id」 来判断 </note>
     *
     * @param list 接口返回最新对账单信息
     * @param req 基础请求对象，用于获取请求渠道、操作人等信息
     * @return 动态质押数据传输集合
     * @author liulx
     * @date 2020-08-18 15:41:53
     */
    @Transactional(rollbackFor = Exception.class)
    protected List<ColdchainDynamicPledgeDTO> processRespListData(List<ColdchainDynamicPledgeResp> list,
        BaseReqObj req) {
        List<ColdchainDynamicPledgeDTO> dtoList = new ArrayList<>(list.size());
        // 业务注解 id 缓存
        List<String> checkIds = new ArrayList<>();
        // 待保存的历史数据信息
        List<ColdchainDynamicPledgeRespHistory> historyList = new ArrayList<>(list.size());
        list.forEach(obj -> {
            // 设置共用字段属性
            ColdchainDynamicPledgeResp tempObj = BeanUtil.setGenericInfo(obj, req);
            // 转换成历史信息，并添加到历史信息集合中
            ColdchainDynamicPledgeRespHistory history = mapper.map(tempObj, ColdchainDynamicPledgeRespHistory.class);
            historyList.add(history);
            // 添加业务主键 id 到集合
            checkIds.add(obj.getDetailId());
            // 转换 DTO 并添加到集合中
            dtoList.add(transformDynamicPledgeDTO(obj));
        });
        // 保存历史表
        dynamicPledgeHistoryModel.saveBatch(historyList);
        LambdaQueryWrapper<ColdchainDynamicPledgeResp> queryWrapper = new LambdaQueryWrapper<>();
        // 根据业务 id 查询返回数据列表中，已存在于数据库里的数据
        queryWrapper.in(ColdchainDynamicPledgeResp::getDetailId, checkIds);
        // 数据库中已存在的数据
        List<ColdchainDynamicPledgeResp> existList = dynamicPledgeModel.list(queryWrapper);

        // 循环判断哪些数据需要更新，哪些是新增
        for (ColdchainDynamicPledgeResp respObj : list) {
            for (ColdchainDynamicPledgeResp existObj : existList) {
                // 找到已存在于数据库中的数据，说明需要更新该信息
                if (respObj.getDetailId().equals(existObj.getDetailId())) {
                    // 将已存在的数据 id，设置到新的数据对象中，按照新的数据对象进行更新
                    respObj.setId(existObj.getId());
                    break;
                }
            }
        }
        // 保存或更新数据
        dynamicPledgeModel.saveOrUpdateBatch(list);
        return dtoList;
    }

    /**
     * 动态数据数据库 entity 转 DTO
     *
     * @param resp 动态数据数据库映射类
     * @return DTO 传输类
     * @author liulx
     */
    protected ColdchainDynamicPledgeDTO transformDynamicPledgeDTO(ColdchainDynamicPledgeResp resp) {
        ColdchainDynamicPledgeDTO dto = new ColdchainDynamicPledgeDTO();
        dto.setId(resp.getDetailId());
        dto.setUserNo(resp.getCustomerNumber());
        dto.setTypeCode(resp.getItem());
        dto.setTypeName(resp.getItemName());
        dto.setLowAmount(resp.getLessAmount());
        dto.setLowWeight(resp.getLessWeight());
        dto.setUserName(resp.getPledge());
        return dto;
    }

    /**
     * 用户查询服务申请
     *
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public synchronized String customerApply(ColdchainCustomerApplyReq req) throws Exception {
        // step1: 调用冷链上传服务
        String response = apiHelper.httpUploadMultipartFormdata(req.getFileUrl(),
            config.getColdchainUrl() + ColdChainUriEnum.UPLOAD_FILE.getUrl(), req);
        JSONObject apiResult = JSONObject.parseObject(response);
        Integer code = apiResult.getInteger("errorCode");
        String message = apiResult.getString("errorMsg");
        if (code == null || code != 0) {
            throw new BusinessException(message, String.valueOf(code));
        }
        String coldChainFileUrl = apiResult.getString("result");
        // step2: 调用冷链申请服务
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", mainBusinessConfig.getColdchainAccount());
        params.put("traceId", req.getApplyId());
        params.put("customerNumber", req.getCustomerNumber());
        params.put("customerName", req.getCustomerName());
        params.put("taxNumber", req.getTaxNumber());
        params.put("fileUrl", coldChainFileUrl);
        params.put("remark", req.getRemark());
        JSONObject result = apiHelper.sendApi(ColdChainUriEnum.CUSTOMER_APPLY, params, req);
        code = result.getInteger("errorCode");
        message = result.getString("errorMsg");
        if (code == null || code != 0) {
            throw new BusinessException(message, String.valueOf(code));
        }
        String applyId = result.getString("result");
        // step3: 新增、修改数据库
        // step3.1: 申请ID没有上送，代表是新申请
        if (StringUtils.isEmpty(req.getApplyId())) {
            // 新增前校验，看看冷链是否返回了重复申请ID
            LambdaQueryWrapper<ColdchainCustomerApply> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ColdchainCustomerApply::getApplyId, applyId);
            ColdchainCustomerApply coldchainCustomerApply = coldchainCustomerApplyMapper.selectOne(queryWrapper);
            if (coldchainCustomerApply != null) {
                throw new BusinessException("申请ID重复：" + applyId + "；请联系冷链工作人员。", "ECRM0000");
            }
            // 新增
            ColdchainCustomerApply customerApply = new ColdchainCustomerApply();
            customerApply.setAccountId(mainBusinessConfig.getColdchainAccount()).setStatus("0")
                .setCustomerNumber(req.getCustomerNumber()).setCustomerName(req.getCustomerName())
                .setTaxNumber(req.getTaxNumber()).setFile_url_channel(req.getFileUrl())
                .setFile_url_coldchain(coldChainFileUrl).setRemark(req.getRemark()).setApplyId(applyId)
                .setCreateBy(req.getOperationUserId()).setGmtCreate(LocalDateTime.now()).setChannel(req.getChannel());
            coldchainCustomerApplyMapper.insert(customerApply);
        }
        // step3.2: 申请ID上送了，代表是拒绝后再次申请，或者是等待审核期间修改申请信息。
        if (!StringUtils.isEmpty(req.getApplyId())) {
            LambdaQueryWrapper<ColdchainCustomerApply> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ColdchainCustomerApply::getApplyId, req.getApplyId());
            ColdchainCustomerApply coldchainCustomerApply = coldchainCustomerApplyMapper.selectOne(queryWrapper);
            if (coldchainCustomerApply != null) {
                // 修改
                coldchainCustomerApply.setAccountId(mainBusinessConfig.getColdchainAccount()).setStatus("0")
                    .setErrorMsg("").setProcTime("").setCustomerNumber(req.getCustomerNumber())
                    .setCustomerName(req.getCustomerName()).setTaxNumber(req.getTaxNumber())
                    .setFile_url_channel(req.getFileUrl()).setFile_url_coldchain(coldChainFileUrl)
                    .setRemark(req.getRemark()).setApplyId(applyId).setGmtModified(LocalDateTime.now())
                    .setModifiedBy(req.getOperationUserId());
                coldchainCustomerApplyMapper.updateById(coldchainCustomerApply);
            }
        }
        return applyId;
    }

    /**
     * 申请结果查询接口
     *
     * @param req
     * @return
     */
    public List<ColdchainApplyResultDTO> applyResultQuery(ApplyResultQueryReq req) {
        Map<String, Object> params = new HashMap<>();
        params = new HashMap<>();
        params.put("accountId", mainBusinessConfig.getColdchainAccount());
        params.put("taxNumber", req.getTaxNumber());
        JSONObject apiResult = apiHelper.sendApi(ColdChainUriEnum.RESULT_QUERY, params, req);
        Integer code = apiResult.getInteger("errorCode");
        String message = apiResult.getString("errorMsg");
        if (code == null || code != 0) {
            throw new BusinessException(message, String.valueOf(code));
        }
        JSONArray result = apiResult.getJSONArray("result");
        // 进行key值转换
        Map<String, String> map = new HashMap<>();
        map.put("traceId", "applyId");
        JSONArray resultChanged = BeanUtil.changeJsonArr(result, map);
        // 传输对象
        List<ColdchainApplyResultDTO> coldchainApplyResultDTOS = new ArrayList<>();
        coldchainApplyResultDTOS = resultChanged.toJavaList(ColdchainApplyResultDTO.class);
        return coldchainApplyResultDTOS;
    }

    /**
     * 接收冷链用户申请结果通知
     *
     * @param req
     * @return
     */
    public String receiveApplyResult(ReceiveApplyResultReq req) {
        // 更新数据库 申请状态
        String applyId = req.getSupplyId();
        LambdaQueryWrapper<ColdchainCustomerApply> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ColdchainCustomerApply::getApplyId, applyId);
        ColdchainCustomerApply coldchainCustomerApply = coldchainCustomerApplyMapper.selectOne(queryWrapper);
        if (coldchainCustomerApply == null) {
            throw new BusinessException("无效的申请ID", "ECRM0000");
        }
        String currentStatus = coldchainCustomerApply.getStatus();
        if ("1".equals(currentStatus) || "2".equals(currentStatus)) {
            throw new BusinessException("指令重复发送:" + applyId, "ECRM0000");
        }
        if (coldchainCustomerApply != null) {
            coldchainCustomerApply.setStatus(req.getStatus()).setProcTime(req.getProcTime())
                .setErrorMsg(req.getErrorMsg()).setGmtModified(LocalDateTime.now())
                .setModifiedBy(req.getOperationUserId());
            coldchainCustomerApplyMapper.updateById(coldchainCustomerApply);
        }
        // mq将结果推给渠道
        Map<String, Object> data = new HashMap<>();
        data.put("traceId", req.getTraceId());
        data.put("requestTime", req.getRequestTime());
        data.put("applyId", req.getSupplyId());
        data.put("procTime", req.getProcTime());
        data.put("status", req.getStatus());
        data.put("errorMsg", req.getErrorMsg());
        data.put("customerNumber", req.getCustomerNumber());
        data.put("customerName", req.getCustomerName());
        data.put("taxNumber", req.getTaxNumber());
        data.put("remark", req.getRemark());
        coldChainProducer.sendMessagesCustomerAnalytics(data);
        String returnsResult = SystemConstant.SYSTEM_SUCCESS;
        return returnsResult;
    }

}
